package com.gitee.wsl.struct.tree

import com.gitee.wsl.ext.base.isTrue
import com.gitee.wsl.struct.tree.builder.ChildDeclaration
import com.gitee.wsl.struct.tree.builder.ChildDeclarationInterface
import com.gitee.wsl.struct.tree.ext.findChild


abstract class AbstractMutableNodeElement<T,E:AbstractMutableNodeElement<T,E>>(
    override var data: T,
    override var parent: E? = null,
    override val children: MutableList<E> = mutableListOf(),
    override val elementId: Any = Unit,
) : NodeElement<T, E>, ChildDeclarationInterface<T,E>, MutableList<E> by children{

//    override fun path(): List<E> =
//        buildList {
//            var next: E? = self()
//            while (next != null) {
//                add(next)
//                next = next.parent
//            }
//        }.reversed()

    override fun add(element:E): Boolean {
        element.parent = self()
        return children.add(element)
    }

    override fun add(index: Int, element: E) {
        element.parent = self()
        children.add(index,element)
    }

    override fun addAll(index: Int, elements: Collection<E>): Boolean {
        elements.forEach { it.parent = self() }
        return children.addAll(index,elements)
    }

    override fun addAll(elements: Collection<E>): Boolean {
        elements.forEach { it.parent = self() }
        return children.addAll(elements)
    }

    /** Remove all children from root and every node in tree. */
    override fun clear() {
        parent = null
        children.forEach { it.clear() }
        children.clear()
    }

    fun removeSelf(){
        parent?.remove(this)
    }

    fun removeChild(element: E): Boolean {
       this.findChild(element)?:return false
       element.removeSelf()
       return true
    }

    override fun remove(element: E): Boolean {
        return children.remove(element).isTrue { element.parent = null }
    }

    override fun removeAll(elements: Collection<E>): Boolean {
        return children.removeAll(elements).isTrue { elements.forEach {  it.parent = null} }
    }

    override fun removeAt(index: Int): E {
        val remove = children.removeAt(index)
        remove.parent = null
        return remove
    }

    override fun set(index: Int, element: E): E {
        val ret = element .set(index, element)
        ret.parent = self()
        return ret
    }

    override fun child(value: T, childDeclaration: ChildDeclaration<T,E>?): E{
        val newChild = createNew(value)
        newChild.parent = self()
        if (childDeclaration != null) newChild.childDeclaration()
        children.add(newChild)
        return newChild
    }

    abstract fun self():E

    abstract fun createNew(value: T):E
}

open class MutableNodeElement<T>(
    data: T,
    parent: MutableNodeElement<T>? = null,
    children: MutableList<MutableNodeElement<T>> = mutableListOf(),
    elementId: Any = Unit,
):AbstractMutableNodeElement<T,MutableNodeElement<T>>(data, parent, children, elementId) {

    override fun self(): MutableNodeElement<T> = this

    override fun createNew(value: T): MutableNodeElement<T> = MutableNodeElement(value)

}